In most cases, programmers write computer applications in high level languages, such as JAVA.sup.1 or C.sup.++, and rely on sophisticated optimizing compilers to convert the high level code into an efficient executable computer program. Optimizing compilers have replaced the time consuming and commercially unfeasible task of handcoding applications in low level assembly or machine-code for maximum efficiency. Instead, an optimizer portion of the compiler performs transformations on the code designed to improve execution times and utilize computer resources more efficiently. Accordingly, some of the code transformations are based on the structure of the code and not related to the target processor used for execution. Other types of transformations improve the code by utilizing specific features available on the target processor such as registers, pipeline structures and other hardware features. FNT 1. The Network Is the Computer, Sun, the Sun logo, Sun Microsystems, Solaris, Ultra and Java are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and in other countries. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the United States and other countries. Products bearing SPARC trademarks are based upon an architecture developed by Sun Microsystems, Inc. UNIX is a registered trademark in the United States and other countries exclusively licensed through X/Open Company, Ltd.
Unfortunately, most optimizes available today only estimate which portions of the program will benefit most from the optimization routines before actual execution. These optimizers analyze the application code in a static state and without any input data. Graphing theory and complex data flow analysis are used at compile time to determine which portions of the code might be executed most frequently at execution time. If these determinations are not correct, frequently executed portions of the code or "hot spots" will not be optimized and the code will run less efficiently. Also, if the application is unusual or behaves in an atypical manner these techniques may also fail to optimize the code effectively.
The current state of optimizing compilers must be significantly improved as the compiler becomes a more integral part of the processor performance. On many pipelined multiple issue processor architectures, the performance of hardware based instruction schedulers have been enhanced using sophisticated optimizing compilers which generate an instruction stream which further exploits the underlying hardware. Unfortunately, these compilers show limited results optimizing computer programs using the current static optimization techniques. In practice, the typical optimizer has difficulty fully optimizing a computer program because the input data and actual runtime characteristics of the computer program are unknown at compile time. Consequently, the optimizer may only increase the performance of a computer program marginally. For example, a very-long-instruction-word (VLIW) computer relies primarily on an optimizing compiler to generate binaries capable of exploiting the VLIW processor's multiple issue capabilities. If the run-time characteristics of a particular computer program are complex, the VLIW optimizing compiler will not be able to predict the run time characteristics of the program and exploit all the processor's features adequately.
Optimizers are also important when comparing processor's based on industry standard benchmarks such as SPECint95, SPECfp95, and TPCC/CB. These standard benchmarks are used to compare different processors based upon how quickly each processor executes the given benchmark program. An inherently powerful processor can appear relatively slow if the optimizing compiler does not optimize the code properly. As a result, the apparent throughput on a processor may be significantly less than a computer manufacturer expects.
What is needed is a dynamic optimizing compiler which uses input data to profile a computer application in a systematic manner suitable for producing a highly optimized executable. These techniques can be used to optimize executables on a wide variety of platforms.